package com.bluemsun.work;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author Steve Paul
 */
public class Commands
{
    //将默认路径设置为java项目路径
    String currentDirectory = System.getProperty("user.dir");

    //cd 改变路径

    /**
     *
     * @param path 要改变成为的路径
     */
    public void cd(String path) {
        Path resolvedPath;
        try {
            resolvedPath = Paths.get(currentDirectory).resolve(path).normalize();
        } catch (Exception ex) {
            System.out.println("您要进入的目录是无效目录");
            return;
        }
        File vFile = resolvedPath.toFile();
        if (!vFile.isDirectory()) {
            System.out.println("您要进入的目录不存在");
        } else {
            this.currentDirectory = resolvedPath.toString();
        }
    }

    //touch 创建新文件

    /**
     *
     * @param filePath 文件名
     * @throws IOException io错误
     */
    public void touch(String filePath) throws IOException {
        Path resolvedPath = Paths.get(currentDirectory).resolve(filePath).normalize();
        File vFile = resolvedPath.toFile();
        //检查是否存在
        if (resolvedPath.startsWith(currentDirectory)) {
            if (vFile.exists()) {
                System.out.println("您要创建的文件已存在,无法创建新文件");
            } else {
                vFile.createNewFile();
                System.out.println("新建" + vFile + "完毕");
            }
        } else {
            System.out.println("touch命令只能在当前目录下新建一个文件");
        }
    }

    //delete 删除文件

    /**
     *
     * @param filePath 文件名
     */
    public void delete(String filePath) {
        Path resolvedPath = Paths.get(currentDirectory).resolve(filePath).normalize();
        File vFile = resolvedPath.toFile();
        //检查是否存在
        if (resolvedPath.startsWith(currentDirectory)) {
            if (vFile.isFile()) {
                vFile.delete();
                System.out.println("删除" + vFile + "完毕");
            } else {
                System.out.println("您要删除的文件不存在");
            }
        } else {
            System.out.println("delete命令只能在当前目录下删除一个文件");
        }
    }

    //mkdir 创建文件夹

    /**
     *
     * @param dirPath 新文件夹的文件夹名
     */
    public void mkdir(String dirPath) {
        Path resolvedPath = Paths.get(currentDirectory).resolve(dirPath).normalize();
        File vDir = resolvedPath.toFile();
        //检查是否存在
        if (resolvedPath.startsWith(currentDirectory)) {
            if (vDir.exists()) {
                System.out.println("您要新建的文件夹已存在");
            } else {
                vDir.mkdir();
                System.out.println("新建" + vDir + "完毕");
            }
        } else {
            System.out.println("mkdir命令只能在当前目录下新建一个文件夹");
        }
    }

    //ls 列出目录下的所有文件/文件夹
    public void ls() {
        File vDir = new File(currentDirectory);
        if (!vDir.exists()) {
            System.out.println("当前目录不存在");
            return;
        }
        File[] subFiles = vDir.listFiles();
        System.out.println(currentDirectory + " 目录下有以下文件/文件夹");
        //对于文件夹和文件分类输出
        if (subFiles != null) {
            System.out.println("文件夹:");
            int cnt = 0;
            for (File f : subFiles) {
                if (f.isDirectory()) {
                    System.out.println(f.getName());
                    cnt++;
                }
            }
            if (cnt == 0) {
                System.out.println("该目录下没有文件夹");
            }
            cnt = 0;
            System.out.println("文件:");
            for (File f : subFiles) {
                if (f.isFile()) {
                    System.out.printf("%15s %15d Byte\n", f.getName(), f.length());
                    cnt++;
                }
            }
            if (cnt == 0) {
                System.out.println("该目录下没有文件");
            }
        }

    }

    //cp 复制文件/文件夹 (写mv顺便写的)
    /**
     * @param originalPath 源路径
     * @param targetPath 目标路径
     * @throws IOException io错误
     */
    public void cp(String originalPath, String targetPath) throws IOException {
        Path oPath = Paths.get(currentDirectory).resolve(originalPath).normalize();
        File oFile = oPath.toFile();
        Path tPath = Paths.get(currentDirectory).resolve(targetPath + File.separator + oFile.getName()).normalize();
        File tFile = tPath.toFile();
        if (!oFile.exists()) {
            System.out.println("您要复制的文件夹/文件的目录不存在");
        } else if (!tPath.getParent().toFile().exists()) {
            System.out.println("您的复制目标目录不存在");
        } else {
            if (oFile.isFile()) {
                System.out.printf("正在复制文件%s\n", oFile.getCanonicalPath());
                if (tFile.exists()) {
                    System.out.printf("此文件%s已存在,请问您想覆盖吗? Y/N\n", tFile.getCanonicalPath());
                    Scanner sc = new Scanner(System.in);
                    char input = sc.nextLine().charAt(0);
                    if (!(input == 'Y' || input == 'y')) {
                        System.out.printf("已取消文件%s的复制\n", oFile.getCanonicalPath());
                        return;
                    }
                }
                FileInputStream fis = new FileInputStream(oFile);
                byte[] buffer = new byte[1024 * 1024];
                FileOutputStream fos = new FileOutputStream(tFile);
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                int n;
                while ((n = fis.read(buffer)) != -1) {
                    bos.write(buffer, 0, n);
                }
                bos.flush();
                fis.close();
                bos.close();
                System.out.printf("已成功复制文件%s\n", oFile.getCanonicalPath());
            }
            if (oFile.isDirectory()) {
                tFile.mkdir();
                File[] subFiles = oFile.listFiles();
                if (subFiles != null) {
                    for (File ele : subFiles) {
                        cp(ele.getCanonicalPath(), tFile.getCanonicalPath());
                    }
                }
            }
        }
    }

    //deletes 删除文件/文件夹(写mv顺便写的)
    public void deletes(String path) throws IOException {
        Path oPath = Paths.get(currentDirectory).resolve(path).normalize();
        File oFile = oPath.toFile();
        if (!oFile.exists()) {
            System.out.println("您要删除的文件/文件夹不存在");
        } else {
            //对于文件和文件夹递归调用删除方法
            if (oFile.isFile()) {
                oFile.delete();
                System.out.printf("已成功删除文件%s\n", oFile.getCanonicalPath());
            }
            if (oFile.isDirectory()) {
                File[] subFiles = oFile.listFiles();
                if (subFiles != null) {
                    for (File ele : subFiles) {
                        deletes(ele.getCanonicalPath());
                    }
                }
                oFile.delete();
            }
        }
    }

    //mv 移动文件/文件夹
    public void mv(String originalPath, String targetPath) throws IOException {
        //利用复制和多重删除方法
        cp(originalPath, targetPath);
        deletes(originalPath);
        System.out.println("移动完毕");
    }

    //cat 查看文件内容 这是对于文本文件的
    public void cat(String filePath) throws IOException {
        Path resolvedPath = Paths.get(currentDirectory).resolve(filePath).normalize();
        File file = resolvedPath.toFile();
        if (!file.isFile()) {
            System.out.println("您想要查看的文件不存在");
            return;
        }
        FileInputStream fis = new FileInputStream(file);
        InputStreamReader isr = new InputStreamReader(fis);
        char[] buffer = new char[1024 * 1024];
        int n;
        while ((n = isr.read(buffer)) != -1) {
            System.out.print(new String(buffer, 0, n));
        }
        System.out.println();
        isr.close();
        System.out.println("已完成文件的读取");
    }

    //write 覆盖写入/追加 这是对于文本文件的
    public void write(String filePath, boolean append) throws IOException {
        Path resolvedPath = Paths.get(currentDirectory).resolve(filePath).normalize();
        File file = resolvedPath.toFile();
        if (!file.isFile()) {
            System.out.println("您想要写入的文件不存在");
            return;
        }
        Scanner sc = new Scanner(System.in);
        System.out.println("请在下面输入您想写入的内容:");
        String str = sc.nextLine();
        FileOutputStream fos = new FileOutputStream(file, append);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        osw.write(str);
        osw.flush();
        osw.close();
        System.out.println("已完成文件写入");
    }

    //help 帮助文档
    public void help() {
        System.out.println("改变路径: cd [路径名]");
        System.out.println("新建文件: touch [文件名]");
        System.out.println("删除文件: delete [文件名]");
        System.out.println("创建文件夹: mkdir [文件夹名]");
        System.out.println("文件列表: ls");
        System.out.println("复制文件/文件夹: cp [原路径] [新路径] , 请注意该命令的意思是把原路径复制到新路径之下,并不是覆盖新路径");
        System.out.println("删除文件/文件夹: deletes [路径名]");
        System.out.println("移动文件/文件夹: mv [原路径] [新路径] , 请注意该命令的意思是把原路径移动到新路径之下,并不是覆盖新路径");
        System.out.println("查看文件: cat [文件名]");
        System.out.println("写入文件: write [文件名] [布尔值] , 请注意布尔值为真即追加,为假即覆盖");
        System.out.println("退出程序: exit");
        System.out.println("查看帮助: help");
    }

    public void commandsAnalyzer() {
        Scanner sc = new Scanner(System.in);
        System.out.print("FM " + currentDirectory + "> ");
        String fullCmd = sc.nextLine();
        //处理字符串参数问题,使用List<String> args来分别装入参数
        String cmd = fullCmd.substring(0, fullCmd.indexOf(' ') != -1 ? fullCmd.indexOf(' ') : fullCmd.length());
        List<String> args = new ArrayList<>();
        StringBuilder arg = new StringBuilder();
        for (int i = fullCmd.indexOf(' ') != -1 ? fullCmd.indexOf(' ') : fullCmd.length() + 1; ; ) {
            if (i >= fullCmd.length()) {
                if (!"".contentEquals(arg)) {
                    args.add(new String(arg));
                }
                break;
            }
            if (fullCmd.charAt(i) == ' ') {
                if (!"".contentEquals(arg)) {
                    args.add(new String(arg));
                    arg = new StringBuilder();
                }
                i++;
            } else {
                if (fullCmd.charAt(i) == '"') {
                    for (int j = i + 1; j < fullCmd.length(); j++) {
                        if (fullCmd.charAt(j) != '"') {
                            arg.append(fullCmd.charAt(j));
                        } else {
                            args.add(new String(arg));
                            arg = new StringBuilder();
                            i = j + 1;
                            break;
                        }
                    }
                } else {
                    arg.append(fullCmd.charAt(i));
                    i++;
                }
            }
        }
        //分类处理命令
        switch (cmd) {
            case "cd": {
                try {
                    cd(args.get(0));
                } catch (IndexOutOfBoundsException ex) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "touch": {
                try {
                    touch(args.get(0));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,新建文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "delete": {
                try {
                    delete(args.get(0));
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "mkdir": {
                try {
                    mkdir(args.get(0));
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "mv": {
                try {
                    mv(args.get(0), args.get(1));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,移动文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "ls": {
                ls();
                break;
            }
            case "write": {
                try {
                    write(args.get(0), Boolean.parseBoolean(args.get(1)));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,写入文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "cat": {
                try {
                    cat(args.get(0));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,读取文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "cp": {
                try {
                    cp(args.get(0), args.get(1));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,复制文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "deletes": {
                try {
                    deletes(args.get(0));
                } catch (IOException ex1) {
                    ex1.printStackTrace();
                    System.out.println("遇到IO错误,删除文件失败");
                } catch (IndexOutOfBoundsException ex2) {
                    System.out.println("您输入的命令无效,试试输入help回车获取更多信息");
                }
                break;
            }
            case "help": {
                help();
                break;
            }
            case "exit": {
                System.exit(0);
            }
            default: {
                System.out.println("您输入的命令无法被识别 拒绝内卷 从我做起");
                System.out.println("该程序支持如下命令");
                help();
                break;
            }
        }
    }
}
